#include "../include/server.h"
#include <errno.h>

#define BACKLOG 10

void Server::addConnection(Connection * _conn) {
	connections.insert(_conn->getId(), _conn);
}

// TODO: IMPLEMENT
void Server::spawn(Server* machine, Connection* _conn);

void Server::handleConnTimeout(c_id_t _conn_id) {
	connections.get(_conn_id).close();
	connections.remove(_conn_id);
}

Server::Server(const char * _interface, 
			port_t _port, 
			int _proto) {
	// Use defaults
	Server(_interface, _port, _proto, 500, 3);
}

Server::Server(const char * _interface, 
			port_t _port, 
			int _proto, 
			long _timeout,
			unsigned int _reconnect) {
	Server(0, _interface, _port, _proto, _timeout, _reconnect);
}

Server::Server(int _sock, 
			const char * _interface, 
			port_t _port, 
			int _proto,
			long _timeout,
			unsigned int _reconnect) {
	listener = sock;
	port = _port;
	protocol = _proto;
	timeout = _timeout;
	reconnect = _reconnect;
	sysErr = 0;
	appErr = 0;
	local_addr.sin_port = htons(_port);
	local_addr.sin_addr = inet_addr(_interface);
	local_addr.sin_family = AF_INET;
}

int Server::start() {
	if(listener == 0) {
		// Create a listener socket
		listener = socket(AF_INET, protocol, 0);
		if(listener < 0) {
			sysErr = errno;
			// TODO: set appErr
			return listener;
		}
		// Bind to local address
		int retval = bind(	listener, 
						(struct sockaddr*)&local_addr,
						sizeof(struct sockaddr_in) );
		if(retval < 0) {
			sysErr = errno;
			// TODO: set appErr
			return retval;
		}
		if(protocol == IPPROTO_TCP) {
			// Listen on socket
			retval = listen(listener, BACKLOG);
			if(retval < 0) {
				sysErr = errno;
				// TODO set appErr
				return retval;
			}
		}
	}
	// TODO: start server loop; possibly in thread
	return 0;
}

void Server::closeConnection() {
	close(listener);
}

void Server::shutDown() {
	for(unsigned int i = 0; i < connections.size(); i++) {
		connections.getAt(i).close();
	}
}
